/*
 * @(#)BeanTree.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.framework.bean;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.commons.beanutils.PropertyUtils;

/**
  BeanTree.java

  This class is to provide a structure to store hierachical bean instances.

    @author          Rollo Chan
    @company         DCIVision Limited
    @creation date   05/09/2003
    @version         $Revision: 1.3 $
*/

public class BeanTree {

  public static final String REVISION = "$Revision: 1.3 $";

  private HashMap treeMap = new HashMap();
  private HashMap beanMap = new HashMap();
  private HashMap parentKeyMap = new HashMap();

  /** Creates a new instance of BeanMap */
  public BeanTree() {
  }

  public List getParentKeyList(Object key) {
    return (List)treeMap.get(key);
  }

  public void put(Object key, Object parentKey, Object bean) {
    LinkedList list = new LinkedList();
    list.add(key);
    List parentList = (List)treeMap.get(parentKey);
    if (parentList!=null) list.addAll(parentList);
    treeMap.put(key,list);
    beanMap.put(key,bean);
    setChild(key,parentKey);
  }

  public void setChild(Object childKey, Object parentKey) {
    Set childIDSet = (Set)parentKeyMap.get(parentKey);
    if (childIDSet==null) {
      childIDSet = new HashSet();
    }
    childIDSet.add(childKey);
    parentKeyMap.put(parentKey,childIDSet);

    Object grandParentKey = getParentKey(parentKey);
    if (grandParentKey!=null) setChild(childKey,grandParentKey);
  }

  public Set getChildList(Object root) {
    return (Set)parentKeyMap.get(root);
  }

  protected Object getParentKey(Object childKey) {
    List branch = (List)treeMap.get(childKey);
    if (branch==null || branch.size()==1) {
      return null;
    } else {
      return branch.get(1);
    }
  }

  public Object get(Object key) {
    return beanMap.get(key);
  }

  public List get(Collection keys) {
    List beansList = new ArrayList();
    Iterator keysIter = keys.iterator();
    while(keysIter.hasNext()) {
      Object key = keysIter.next();
      beansList.add(beanMap.get(key));
    }
    return beansList;
  }

  public Object getProperty(Object key,String keyProperty) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    Object value = beanMap.get(key);
    return PropertyUtils.getProperty(value, keyProperty);
  }

  public boolean containsChild(Object key, Collection childsKey) {
    boolean isContain=false;

    Set childIDSet = (Set)parentKeyMap.get(key);
    if (childIDSet==null) return false;

    if (childsKey!=null) {
      Iterator iter = childsKey.iterator();
      while(iter.hasNext() && isContain==false) {
        isContain = childIDSet.contains(iter.next());
      }
      return isContain;
    } else {
      return true;
    }
  }

  public boolean containsAllChild(Object key, Collection childsKey) {
    boolean isContain=true;

    Set childIDSet = (Set)parentKeyMap.get(key);
    if (childIDSet==null) return false;

    if (childsKey!=null) {
      Iterator iter = childsKey.iterator();
      while(iter.hasNext() && isContain) {
        isContain &= childIDSet.contains(iter.next());
      }
    }
    return isContain;
  }

  public String toString() {
    return (treeMap.values()).toString();
  }
}
